package com.tianji.aigc.memory;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.json.JSONUtil;
import com.tianji.aigc.config.ToolResultHolder;
import com.tianji.aigc.constants.Constant;
import org.springframework.ai.chat.messages.*;

import java.util.Map;

/**
 * 消息转换工具类，提供消息对象与JSON字符串之间的转换功能，主要用于Redis存储格式转换
 */
public class MessageUtil {

    /**
     * 将Message对象转换为Redis存储格式的JSON字符串
     *
     * @param message 需要转换的原始消息对象
     * @return 符合Redis存储规范的JSON字符串
     */
    public static String toJson(Message message) {
        var convertMessage = BeanUtil.toBean(message, ConvertMessage.class);
        // 设置消息内容
        convertMessage.setTextContent(message.getText());
        if (message instanceof AssistantMessage assistantMessage) {
            convertMessage.setToolCalls(assistantMessage.getToolCalls());
            // 如果有参数信息，将参数信息添加到JSON字符串中
            String messageId = Convert.toStr(message.getMetadata().get("id"));
            String requestId = Convert.toStr(ToolResultHolder.get(messageId, Constant.REQUEST_ID));
            Map<String, Object> params = ToolResultHolder.get(requestId);
            if (ObjUtil.isNotEmpty(params)) {
                // 持久化参数信息：即手动在FLux流结束前拼接的参数，
                // 此处用于持久化卡片数据的课程信息、预下单信息数据，用于在查询历史会话时展示
                convertMessage.setParams(params);
            }
            // 用完即，清除本地缓存中的参数数据
            ToolResultHolder.remove(messageId);
        }

        if (message instanceof ToolResponseMessage toolResponseMessage) {
            convertMessage.setToolResponses(toolResponseMessage.getResponses());
        }

        return JSONUtil.toJsonStr(convertMessage);
    }

    /**
     * 将Redis存储的JSON字符串反序列化为对应的Message对象
     *
     * @param json Redis存储的JSON格式消息数据
     * @return 对应类型的Message对象
     * @throws RuntimeException 当无法识别的消息类型时抛出异常
     */
    public static Message toMessage(String json) {
        var convertMessage = JSONUtil.toBean(json, ConvertMessage.class);
        var messageType = MessageType.valueOf(convertMessage.getMessageType());
        switch (messageType) {
            case SYSTEM -> {
                return new SystemMessage(convertMessage.getTextContent());
            }
            case USER -> {
                return new UserMessage(convertMessage.getTextContent(), convertMessage.getMedia(), convertMessage.getMetadata());
            }
            case ASSISTANT -> {
                return new CustomizeAssistantMessage(convertMessage.getTextContent(), convertMessage.getProperties(), convertMessage.getToolCalls(), convertMessage.getParams());
            }
            case TOOL -> {
                return new ToolResponseMessage(convertMessage.getToolResponses(), convertMessage.getMetadata());
            }
        }

        throw new RuntimeException("Message data conversion failed.");
    }

}
